Skip to content

Upload data api three layer refactor#14798

Open
osama-rizk wants to merge 25 commits intomainfrom
upload-data-api-three-layer-refactor
Open

Upload data api three layer refactor#14798
osama-rizk wants to merge 25 commits intomainfrom
upload-data-api-three-layer-refactor

Conversation

@osama-rizk
Copy link
Copy Markdown
Contributor

@osama-rizk osama-rizk commented Apr 30, 2026

Description of changes

Refactor the internal uploadData API in @aws-amplify/storage to follow the
three-layer architecture (foundation / client / server):

  • foundation/ — environment-agnostic core. Contains calculateContentCRC32
    and calculateContentMd5, which now receive a FoundationContext
    ({ amplify, readFile, toBase64 }) via dependency injection instead of
    branching on the runtime.
  • client/ — browser + React Native implementations of readFile and
    toBase64 (with .native.ts splits preserved), plus the public
    client-side uploadData API.
  • server/ — Node.js implementations and the public server-side
    uploadData API, which injects the request-scoped Amplify instance from
    getAmplifyServerContext.

The uploadData call graph (putObjectJob, getMultipartUploadHandlers,
uploadPartExecutor, loadOrCreateMultipartUpload) now threads
FoundationContext instead of AmplifyClassV6, so the foundation layer is
fully free of environment-discriminating logic.

Public API surface is unchanged. Routing to the correct bundle per
environment is handled via conditional exports in package.json
(browser / import / require), and the existing
aws-amplify/storage/server subpath is preserved for backward compatibility.

Legacy providers/s3/utils/{crc32,md5,readFile}.ts are kept as shims for
deleteObjects until remove is migrated; new code imports from
foundation/utils and client|server/utils instead.

This is the first API migrated to the three-layer pattern; follow-up PRs
will apply the same split to the remaining Storage APIs.

Issue #, if available

N/A — internal refactor, no customer-facing behavior change.

Description of how you validated changes

  • Existing unit tests for uploadData updated to pass FoundationContext
    instead of Amplify; all continue to pass.
  • Added direct unit tests for the new foundation/utils/*,
    client/utils/*, and server/utils/* modules. New code has 100%
    statement/function/line coverage.
  • aws-amplify Jest config now runs two projects so the umbrella
    package's exports are verified under both resolution paths:
    • node project (pinned customExportConditions: ['node']) — existing
      tests, asserts the SSR surface of @aws-amplify/storage in
      exports.test.ts.
    • browser project (jsdom defaults) — new exports.browser.test.ts
      asserts the full client-side surface (uploadData, downloadData,
      remove, list, getProperties, copy, getUrl, isCancelError,
      StorageError, DEFAULT_PART_SIZE).
    • babel-jest with @babel/preset-env (modules: 'commonjs') is used
      to transform the .mjs ESM bundle emitted by @aws-amplify/storage
      so Jest can load it under the browser condition; ts-jest continues to
      handle .ts/.js.
  • predictions Jest config no longer pins the node export condition.
    It provides a global moduleNameMapper stub for @aws-amplify/storage
    (predictions only consumes getUrl), which removes the need for a
    resolution pin. Existing per-test jest.mock(...) overrides still work.
  • yarn test passes for the storage, aws-amplify, and predictions
    packages. Package-level coverage thresholds respected.

Checklist

  • PR description included
  • yarn test passes
  • Unit Tests are changed or added
  • Relevant documentation is changed or added (and PR referenced)

Checklist for repo maintainers

  • Verify E2E tests for existing workflows are working as expected or add E2E tests for newly added workflows
  • New source file paths included in this PR have been added to CODEOWNERS, if appropriate

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 30, 2026

🦋 Changeset detected

Latest commit: 2e18fed

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@aws-amplify/storage Minor
aws-amplify Minor
@aws-amplify/predictions Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@osama-rizk osama-rizk changed the base branch from feat/storage/upload-data-api to main April 30, 2026 15:58
@osama-rizk osama-rizk changed the base branch from main to feat/storage/upload-data-api April 30, 2026 16:02
@osama-rizk osama-rizk force-pushed the upload-data-api-three-layer-refactor branch from 9726d21 to 97d6321 Compare April 30, 2026 16:05
Base automatically changed from feat/storage/upload-data-api to main May 4, 2026 08:20
@osama-rizk osama-rizk added the run-tests run the pr-label workflow label May 5, 2026
@osama-rizk osama-rizk marked this pull request as ready for review May 5, 2026 12:01
@osama-rizk osama-rizk requested review from a team, avi-karthik, pranavosu and sarayev as code owners May 5, 2026 12:01
bobbor
bobbor previously approved these changes May 8, 2026
return Buffer.from(input, 'utf-8').toString('base64');
}

return Buffer.from(input.buffer).toString('base64');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both the React Native and server toBase64 implementations ignore byteOffset and byteLength. The browser implementation correctly uses new Uint8Array(input.buffer, input.byteOffset, input.byteLength)

Copy link
Copy Markdown
Contributor Author

@osama-rizk osama-rizk May 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated both implementation (server & RN ) ✅

soberm
soberm previously approved these changes May 8, 2026
Copy link
Copy Markdown
Member

@bobbor bobbor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking at the 3 files (client/utils/toBase64.ts, client/utils/toBase64.native.ts and server/utils/toBase64.ts) they all do the same and can result in a foundation/utils/toBase64.ts.

the client file uses low-level constructs (Uint8Array, TextEncoder and btoa) which are available in all environments.

so I'd suggest:

  1. take the client/util/toBase64.ts move that to foundation/util/toBase64.ts + test
  2. remove the native and server implementations + tests
  3. remove the toBase64 from the FoundationContext

Replace the per-environment client/server toBase64 implementations with a
single foundation/utils/toBase64.ts. The browser-style impl using
TextEncoder/btoa/Uint8Array works in all supported runtimes (Node 18+,
modern browsers, React Native), so toBase64 no longer needs DI through
FoundationContext.
@osama-rizk
Copy link
Copy Markdown
Contributor Author

looking at the 3 files (client/utils/toBase64.ts, client/utils/toBase64.native.ts and server/utils/toBase64.ts) they all do the same and can result in a foundation/utils/toBase64.ts.

the client file uses low-level constructs (Uint8Array, TextEncoder and btoa) which are available in all environments.

so I'd suggest:

  1. take the client/util/toBase64.ts move that to foundation/util/toBase64.ts + test
  2. remove the native and server implementations + tests
  3. remove the toBase64 from the FoundationContext

Done ✅ toBase64 is consolidated and are part of the foundation layer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-tests run the pr-label workflow

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants